package co.yixiang.yshop.module.product.service.storeproduct;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import co.yixiang.yshop.framework.common.enums.ShopCommonEnum;
import co.yixiang.yshop.framework.common.pojo.PageResult;
import co.yixiang.yshop.module.product.api.product.dto.ProductPageReqVO;
import co.yixiang.yshop.module.product.controller.admin.storeproduct.vo.*;
import co.yixiang.yshop.module.product.controller.app.campaigninfo.vo.AppCampaignSkuRespVO;
import co.yixiang.yshop.module.product.convert.storeproduct.StoreProductConvert;
import co.yixiang.yshop.module.product.convert.storeproductattrvalue.StoreProductAttrValueConvert;
import co.yixiang.yshop.module.product.convert.storeproductrule.StoreProductRuleConvert;
import co.yixiang.yshop.module.product.dal.dataobject.category.ProductCategoryDO;
import co.yixiang.yshop.module.product.dal.dataobject.storeproduct.StoreProductDO;
import co.yixiang.yshop.module.product.dal.dataobject.storeproductattrresult.StoreProductAttrResultDO;
import co.yixiang.yshop.module.product.dal.dataobject.storeproductattrvalue.StoreProductAttrValueDO;
import co.yixiang.yshop.module.product.dal.dataobject.storeproductrule.StoreProductRuleDO;
import co.yixiang.yshop.module.product.dal.mysql.campaigndetail.CampaignDetailMapper;
import co.yixiang.yshop.module.product.dal.mysql.storeproduct.StoreProductMapper;
import co.yixiang.yshop.module.product.enums.common.PageTypeEnum;
import co.yixiang.yshop.module.product.enums.coupon.CouponScopeEnum;
import co.yixiang.yshop.module.product.enums.product.SpecTypeEnum;
import co.yixiang.yshop.module.product.service.category.ProductCategoryService;
import co.yixiang.yshop.module.product.service.producttag.ProductTagService;
import co.yixiang.yshop.module.product.service.shippingtemplates.ShippingTemplatesService;
import co.yixiang.yshop.module.product.service.storeproduct.dto.*;
import co.yixiang.yshop.module.product.service.storeproductattr.StoreProductAttrService;
import co.yixiang.yshop.module.product.service.storeproductattrresult.StoreProductAttrResultService;
import co.yixiang.yshop.module.product.service.storeproductattrvalue.StoreProductAttrValueService;
import co.yixiang.yshop.module.product.service.storeproductrule.StoreProductRuleService;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

import static co.yixiang.yshop.framework.common.exception.util.ServiceExceptionUtil.exception;
import static co.yixiang.yshop.module.product.enums.ErrorCodeConstants.*;

/**
 * 商品 Service 实现类
 *
 * @author yshop
 */
@Service
@Validated
public class StoreProductServiceImpl extends ServiceImpl<StoreProductMapper, StoreProductDO> implements StoreProductService {

    @Resource
    private StoreProductMapper storeProductMapper;
    @Resource
    private StoreProductAttrValueService storeProductAttrValueService;
    @Resource
    private StoreProductAttrService storeProductAttrService;
    @Resource
    private StoreProductRuleService storeProductRuleService;
    @Resource
    private StoreProductAttrResultService storeProductAttrResultService;
    @Resource
    private ProductCategoryService productCategoryService;
    @Resource
    private ShippingTemplatesService shippingTemplatesService;
    @Resource
    private ProductTagService productTagService;

    @Resource
    private CampaignDetailMapper campaignDetailMapper;

    @Override
    public Long createStoreProduct(StoreProductCreateReqVO createReqVO) {
        // 插入
        StoreProductDO storeProduct = StoreProductConvert.INSTANCE.convert(createReqVO);
        storeProductMapper.insert(storeProduct);
        // 返回
        return storeProduct.getId();
    }

    @Override
    public void updateStoreProduct(StoreProductUpdateReqVO updateReqVO) {
        // 校验存在
        validateStoreProductExists(updateReqVO.getId());
        // 更新
        StoreProductDO updateObj = StoreProductConvert.INSTANCE.convert(updateReqVO);
        storeProductMapper.updateById(updateObj);
    }

    @Override
    public void deleteStoreProduct(Long id) {
        // 校验存在
        validateStoreProductExists(id);
        // 删除
        storeProductMapper.deleteById(id);
    }

    private void validateStoreProductExists(Long id) {
        if (storeProductMapper.selectById(id) == null) {
            throw exception(STORE_PRODUCT_NOT_EXISTS);
        }
    }

    @Override
    public StoreProductDO getStoreProduct(Long id) {
        return storeProductMapper.selectById(id);
    }

    @Override
    public List<StoreProductDO> getStoreProductList(Collection<Long> ids) {
        return storeProductMapper.selectBatchIds(ids);
    }

    @Override
    public PageResult<StoreProductDO> getCouponProductPage(CouponProductPageReqVO pageReqVO) {
        LambdaQueryWrapper<StoreProductDO> queryWrapper = new LambdaQueryWrapper<>();
        if (CouponScopeEnum.PRODUCT.getValue().equals(pageReqVO.getCouponScope())) {
            queryWrapper.in(StoreProductDO::getId, pageReqVO.getIds());
        }
        return storeProductMapper.selectPage(pageReqVO, queryWrapper);
    }

    @Override
    public PageResult<StoreProductDO> getStoreProductPage(StoreProductPageReqVO pageReqVO) {
        if (pageReqVO.getCateId() != null) {
            ProductCategoryDO productCategoryDO = productCategoryService.getCategory(Convert.toLong(pageReqVO.getCateId()));
            if (productCategoryDO != null) {
                List<Long> catIds = new ArrayList<>();
                if (Objects.equals(productCategoryDO.getParentId(), ProductCategoryDO.PARENT_ID_NULL)) {
                    catIds = productCategoryService.list((Wrappers.<ProductCategoryDO>lambdaQuery()
                                    .eq(ProductCategoryDO::getParentId, productCategoryDO.getId())))
                            .stream().map(ProductCategoryDO::getId).collect(Collectors.toList());
                } else {
                    catIds.add(Convert.toLong(pageReqVO.getCateId()));
                }
                pageReqVO.setCatIds(catIds);
            }
        }
        return storeProductMapper.selectPage(pageReqVO);
    }

    @Override
    public PageResult<CampaignProductRespVO> getCampaignProductPage(CampaignProductPageReqVO pageReqVO) {
        PageResult<CampaignProductRespVO> result =
                StoreProductConvert.INSTANCE.campaignConvertPage(storeProductMapper.getCampaignProductPage(pageReqVO));
        List<CampaignProductRespVO> products = result.getList();
        if (CollectionUtils.isEmpty(products)) return result;
        // 查询规格信息
        List<Long> productId = products.stream().map(CampaignProductRespVO::getId).collect(Collectors.toList());
        List<CampaignSkuRespVO> skus =
                StoreProductAttrValueConvert.INSTANCE.convertList(storeProductAttrValueService
                        .getStoreProductAttrValueByProductIds(productId));
        if (CollectionUtils.isEmpty(skus)) return result;
        Map<Long, List<CampaignSkuRespVO>> skuMap =
                skus.stream().collect(Collectors.groupingBy(CampaignSkuRespVO::getProductId));
        for (CampaignProductRespVO product : products) {
            product.setSkus(skuMap.get(product.getId()));
        }
        return result;
    }

    @Override
    public List<StoreProductDO> getStoreProductList(StoreProductExportReqVO exportReqVO) {
        return storeProductMapper.selectList(exportReqVO);
    }

    /**
     * 获取生成的属性
     *
     * @param id      商品id
     * @param jsonStr jsonStr
     * @return map
     */
    @Override
    public Map<String, Object> getFormatAttr(Long id, String jsonStr, boolean isActivity) {
        JSONObject jsonObject = JSON.parseObject(jsonStr);
        Map<String, Object> resultMap = new LinkedHashMap<>(3);

        if (jsonObject == null || jsonObject.get("attrs") == null || jsonObject.getJSONArray("attrs").isEmpty()) {
            resultMap.put("attr", new ArrayList<>());
            resultMap.put("value", new ArrayList<>());
            resultMap.put("header", new ArrayList<>());
            return resultMap;
        }

        List<FormatDetailDTO> formatDetailDTOList = JSON.parseArray(jsonObject.get("attrs").toString(),
                FormatDetailDTO.class);
        //formatDetailDTOList
        DetailDTO detailDto = this.attrFormat(formatDetailDTOList);

        List<Map<String, Object>> headerMapList = null;
        List<Map<String, Object>> valueMapList = new ArrayList<>();
        String align = "center";
        Map<String, Object> headerMap = new LinkedHashMap<>();
        for (Map<String, Map<String, String>> map : detailDto.getRes()) {
            Map<String, String> detail = map.get("detail");
            String[] detailArr = detail.values().toArray(new String[]{});
            //   Arrays.sort(detailArr);

            String sku = String.join(",", detailArr);

            Map<String, Object> valueMap = new LinkedHashMap<>();

            List<String> detailKeys = new ArrayList<>(detail.keySet());

            int i = 0;
            headerMapList = new ArrayList<>();
            for (String title : detailKeys) {
                headerMap.put("title", title);
                headerMap.put("minWidth", "130");
                headerMap.put("align", align);
                headerMap.put("key", "value" + (i + 1));
                headerMap.put("slot", "value" + (i + 1));
                headerMapList.add(ObjectUtil.clone(headerMap));
                i++;
            }

            String[] detailValues = detail.values().toArray(new String[]{});
            for (int j = 0; j < detailValues.length; j++) {
                String key = "value" + (j + 1);
                valueMap.put(key, detailValues[j]);
            }
//            /** 拼团属性对应的金额 */
//            private BigDecimal pinkPrice;
//
//            /** 秒杀属性对应的金额 */
//            private BigDecimal seckillPrice;
//            /** 拼团库存属性对应的库存 */
//            private Integer pinkStock;
//
//            private Integer seckillStock;
            valueMap.put("detail", detail);
            valueMap.put("sku", "");
            valueMap.put("pic", "");
            valueMap.put("price", 0);
            valueMap.put("cost", 0);
            valueMap.put("ot_price", 0);
            valueMap.put("stock", 0);
            valueMap.put("bar_code", "");
            valueMap.put("weight", 0);
            valueMap.put("volume", 0);
            valueMap.put("brokerage", 0);
            valueMap.put("brokerage_two", 0);
            valueMap.put("pink_price", 0);
            valueMap.put("seckill_price", 0);
            valueMap.put("pink_stock", 0);
            valueMap.put("seckill_stock", 0);
            valueMap.put("integral", 0);
            if (id > 0) {
                StoreProductAttrValueDO storeProductAttrValue = storeProductAttrValueService
                        .getOne(Wrappers.<StoreProductAttrValueDO>lambdaQuery()
                                .eq(StoreProductAttrValueDO::getProductId, id)
                                .eq(StoreProductAttrValueDO::getSku, sku));
                if (storeProductAttrValue != null) {
                    valueMap.put("sku", storeProductAttrValue.getSku());
                    valueMap.put("pic", storeProductAttrValue.getImage());
                    valueMap.put("price", storeProductAttrValue.getPrice());
                    valueMap.put("cost", storeProductAttrValue.getCost());
                    valueMap.put("ot_price", storeProductAttrValue.getOtPrice());
                    valueMap.put("stock", storeProductAttrValue.getStock());
                    valueMap.put("bar_code", storeProductAttrValue.getBarCode());
                    valueMap.put("weight", storeProductAttrValue.getWeight());
                    valueMap.put("volume", storeProductAttrValue.getVolume());
                    valueMap.put("brokerage", storeProductAttrValue.getBrokerage());
                    valueMap.put("brokerage_two", storeProductAttrValue.getBrokerageTwo());
                    valueMap.put("pink_price", storeProductAttrValue.getPinkPrice());
                    valueMap.put("seckill_price", storeProductAttrValue.getSeckillPrice());
                    valueMap.put("pink_stock", storeProductAttrValue.getPinkStock());
                    valueMap.put("seckill_stock", storeProductAttrValue.getSeckillStock());
                    valueMap.put("integral", storeProductAttrValue.getIntegral());
                    valueMap.put("firstWages", storeProductAttrValue.getFirstWages());
                    valueMap.put("secondWages", storeProductAttrValue.getSecondWages());
                }
            }

            valueMapList.add(ObjectUtil.clone(valueMap));

        }

        assert headerMapList != null;
        this.addMap(headerMap, headerMapList, align, isActivity);


        resultMap.put("attr", formatDetailDTOList);
        resultMap.put("value", valueMapList);
        resultMap.put("header", headerMapList);

        return resultMap;
    }

    /**
     * 增加表头
     *
     * @param headerMap     headerMap
     * @param headerMapList headerMapList
     * @param align         align
     */
    private void addMap(Map<String, Object> headerMap, List<Map<String, Object>> headerMapList, String align, boolean isActivity) {
        headerMap.put("title", "图片");
        headerMap.put("slot", "pic");
        headerMap.put("align", align);
        headerMap.put("minWidth", 80);
        headerMapList.add(ObjectUtil.clone(headerMap));

        headerMap.put("title", "售价");
        headerMap.put("slot", "price");
        headerMap.put("align", align);
        headerMap.put("minWidth", 120);
        headerMapList.add(ObjectUtil.clone(headerMap));

        headerMap.put("title", "成本价");
        headerMap.put("slot", "cost");
        headerMap.put("align", align);
        headerMap.put("minWidth", 140);
        headerMapList.add(ObjectUtil.clone(headerMap));

        headerMap.put("title", "原价");
        headerMap.put("slot", "ot_price");
        headerMap.put("align", align);
        headerMap.put("minWidth", 140);
        headerMapList.add(ObjectUtil.clone(headerMap));

        headerMap.put("title", "库存");
        headerMap.put("slot", "stock");
        headerMap.put("align", align);
        headerMap.put("minWidth", 140);
        headerMapList.add(ObjectUtil.clone(headerMap));

        headerMap.put("title", "产品编号");
        headerMap.put("slot", "bar_code");
        headerMap.put("align", align);
        headerMap.put("minWidth", 140);
        headerMapList.add(ObjectUtil.clone(headerMap));

        headerMap.put("title", "重量(KG)");
        headerMap.put("slot", "weight");
        headerMap.put("align", align);
        headerMap.put("minWidth", 140);
        headerMapList.add(ObjectUtil.clone(headerMap));

        headerMap.put("title", "体积(m³)");
        headerMap.put("slot", "volume");
        headerMap.put("align", align);
        headerMap.put("minWidth", 140);
        headerMapList.add(ObjectUtil.clone(headerMap));

//        headerMap.put("title", "所需兑换积分");
//        headerMap.put("slot", "integral");
//        headerMap.put("align", align);
//        headerMap.put("minWidth", 140);
//        headerMapList.add(ObjectUtil.clone(headerMap));

        if (isActivity) {
            headerMap.put("title", "拼团价");
            headerMap.put("slot", "pink_price");
            headerMap.put("align", align);
            headerMap.put("minWidth", 140);
            headerMapList.add(ObjectUtil.clone(headerMap));

            headerMap.put("title", "拼团活动库存");
            headerMap.put("slot", "pink_stock");
            headerMap.put("align", align);
            headerMap.put("minWidth", 140);
            headerMapList.add(ObjectUtil.clone(headerMap));

            headerMap.put("title", "秒杀价");
            headerMap.put("slot", "seckill_price");
            headerMap.put("align", align);
            headerMap.put("minWidth", 140);
            headerMapList.add(ObjectUtil.clone(headerMap));

            headerMap.put("title", "秒杀活动库存");
            headerMap.put("slot", "seckill_stock");
            headerMap.put("align", align);
            headerMap.put("minWidth", 140);
            headerMapList.add(ObjectUtil.clone(headerMap));
        }

        headerMap.put("title", "操作");
        headerMap.put("slot", "action");
        headerMap.put("align", align);
        headerMap.put("minWidth", 70);
        headerMapList.add(ObjectUtil.clone(headerMap));
    }


    /**
     * 组合规则属性算法
     *
     * @param formatDetailDTOList 组合规则算法对象
     * @return DetailDto
     */
    private DetailDTO attrFormat(List<FormatDetailDTO> formatDetailDTOList) {

        List<String> data = new ArrayList<>();
        List<Map<String, Map<String, String>>> res = new ArrayList<>();

        formatDetailDTOList.stream()
                .map(FormatDetailDTO::getDetail)
                .forEach(i -> {
                    if (i == null || i.isEmpty()) {
                        throw exception(STORE_PRODUCT_RULE_NEED);
                    }
                    String str = ArrayUtil.join(i.toArray(), ",");
                    if (str.contains("-")) {
                        throw exception(STORE_PRODUCT_RULE_RE);
                    }
                });

        if (formatDetailDTOList.size() > 1) {
            for (int i = 0; i < formatDetailDTOList.size() - 1; i++) {
                if (i == 0) {
                    data = formatDetailDTOList.get(i).getDetail();
                }
                List<String> tmp = new LinkedList<>();
                for (String valueStr : data) {
                    for (String g : formatDetailDTOList.get(i + 1).getDetail()) {
                        String rep2 = "";
                        if (i == 0) {
                            rep2 = formatDetailDTOList.get(i).getValue() + "_" + valueStr + "-"
                                    + formatDetailDTOList.get(i + 1).getValue() + "_" + g;
                        } else {
                            rep2 = valueStr + "-"
                                    + formatDetailDTOList.get(i + 1).getValue() + "_" + g;
                        }

                        tmp.add(rep2);

                        if (i == formatDetailDTOList.size() - 2) {
                            Map<String, Map<String, String>> repMap = getMap(rep2);
                            res.add(repMap);
                        }
                    }

                }

                if (!tmp.isEmpty()) {
                    data = tmp;
                }
            }
        } else {
            List<String> dataArr = new ArrayList<>();
            for (FormatDetailDTO formatDetailDTO : formatDetailDTOList) {
                for (String str : formatDetailDTO.getDetail()) {
                    Map<String, Map<String, String>> detailMap = new LinkedHashMap<>();
                    dataArr.add(formatDetailDTO.getValue() + "_" + str);
                    Map<String, String> map1 = new LinkedHashMap<>();
                    map1.put(formatDetailDTO.getValue(), str);
                    detailMap.put("detail", map1);
                    res.add(detailMap);
                }
            }
            String s = StrUtil.join("-", dataArr);
            data.add(s);
        }

        DetailDTO detailDto = new DetailDTO();
        detailDto.setData(data);
        detailDto.setRes(res);

        return detailDto;
    }

    private static Map<String, Map<String, String>> getMap(String rep2) {
        Map<String, Map<String, String>> repMap = new LinkedHashMap<>();
        Map<String, String> repTempMap = new LinkedHashMap<>();
        for (String h : rep2.split("-")) {
            List<String> splitList = Arrays.asList(h.split("_"));
            if (splitList.size() > 1) {
                StringBuilder tempStr = new StringBuilder();
                //前面用_分割导致名称中带多个_被去掉，所以重组的时候需要拼上
                for (int j = 1; j < splitList.size(); j++) {
                    if (j == splitList.size() - 1) {
                        tempStr.append(splitList.get(j));
                    } else {
                        tempStr.append(splitList.get(j)).append("_");
                    }
                }
                repTempMap.put(splitList.get(0), tempStr.toString());
            } else {
                repTempMap.put(splitList.get(0), "");
            }
        }
        repMap.put("detail", repTempMap);
        return repMap;
    }

    /**
     * 新增/保存商品
     *
     * @param storeProductDTO 商品
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void insertAndEditYxStoreProduct(StoreProductDTO storeProductDTO) {
        ProductResultDTO resultDTO = this.computedProduct(storeProductDTO.getAttrs());
        validPrice(storeProductDTO);
        //添加商品
        StoreProductDO yxStoreProduct = new StoreProductDO();
        BeanUtil.copyProperties(storeProductDTO, yxStoreProduct, "sliderImage");
        if (storeProductDTO.getSliderImage().isEmpty()) {
            throw exception(STORE_PRODUCT_SLIDER_ERROR);
        }

        yxStoreProduct.setPrice(BigDecimal.valueOf(resultDTO.getMinPrice()));
        yxStoreProduct.setOtPrice(BigDecimal.valueOf(resultDTO.getMinOtPrice()));
        yxStoreProduct.setCost(BigDecimal.valueOf(resultDTO.getMinCost()));
        yxStoreProduct.setIntegral(resultDTO.getMinIntegral());
        yxStoreProduct.setStock(resultDTO.getStock());
        yxStoreProduct.setSliderImage(String.join(",", storeProductDTO.getSliderImage()));

//        if (storeProductDto.getId() != null) {
//            //清空商品转发图
//            deleteForwardImg(storeProductDto.getId());
//        }


        this.saveOrUpdate(yxStoreProduct);

        //属性处理
        //处理单sKu
        if (SpecTypeEnum.SINGLE_SPECS.getValue().equals(storeProductDTO.getSpecType())) {
            FormatDetailDTO formatDetailDTO = FormatDetailDTO.builder()
                    .value("规格")
                    .detailValue("")
                    .attrHidden("")
                    .detail(ListUtil.toList("默认"))
                    .build();
            List<ProductFormatDTO> attrs = storeProductDTO.getAttrs();
            ProductFormatDTO productFormatDto = attrs.get(0);
            productFormatDto.setValue1("规格");
            Map<String, String> map = new HashMap<>();
            map.put("规格", "默认");
            productFormatDto.setDetail(map);
            storeProductAttrService.insertYxStoreProductAttr(ListUtil.toList(formatDetailDTO),
                    ListUtil.toList(productFormatDto), yxStoreProduct.getId());
        } else {
            storeProductAttrService.insertYxStoreProductAttr(storeProductDTO.getItems(),
                    storeProductDTO.getAttrs(), yxStoreProduct.getId());
        }


    }

    private void validPrice(StoreProductDTO storeProductDto) {
        for (ProductFormatDTO dto : storeProductDto.getAttrs()) {
            if (dto.getPrice() <= 0) throw exception(STORE_PRODUCT_PRICE_ERROR);
        }
    }

    @Override
    public Map<String, Object> getProductInfo(Long id) {
        Map<String, Object> map = new LinkedHashMap<>(3);
        //运费模板
        map.put("tempList", shippingTemplatesService.list());


        //商品规格
        List<StoreProductRuleDO> list = storeProductRuleService.getStoreProductRuleList(CollUtil.newArrayList());
        map.put("ruleList", StoreProductRuleConvert.INSTANCE.convertList(list));
        if (id == 0) {
            return map;
        }

        //处理商品详情
        StoreProductDO storeProduct = storeProductMapper.selectById(id);
        ProductDTO productDto = new ProductDTO();
        BeanUtil.copyProperties(storeProduct, productDto, "sliderImage");
        productDto.setSliderImage(Arrays.asList(storeProduct.getSliderImage().split(",")));
        //商品标签
        Long productTagId = storeProduct.getProductTagId();
        if (productTagId != null) {
            productDto.setTag(productTagService.findTagById(productTagId));
        }
        StoreProductAttrResultDO storeProductAttrResult = storeProductAttrResultService
                .getOne(Wrappers.<StoreProductAttrResultDO>lambdaQuery()
                        .eq(StoreProductAttrResultDO::getProductId, id).last("limit 1"));
        if (storeProductAttrResult == null) {
            map.put("productInfo", productDto);
            return map;
        }
        JSONObject result = JSON.parseObject(storeProductAttrResult.getResult());
        List<StoreProductAttrValueDO> attrValues = storeProductAttrValueService.list(new LambdaQueryWrapper<StoreProductAttrValueDO>().eq(StoreProductAttrValueDO::getProductId, id));
        List<ProductFormatDTO> productFormatDTOList = attrValues.stream().map(i -> {
            ProductFormatDTO productFormatDto = new ProductFormatDTO();
            BeanUtils.copyProperties(i, productFormatDto);
            productFormatDto.setPic(i.getImage());
            return productFormatDto;
        }).collect(Collectors.toList());
        if (SpecTypeEnum.MULTIPLE_SPECS.getValue().equals(storeProduct.getSpecType())) {
            productDto.setAttr(new ProductFormatDTO());
            productDto.setAttrs(productFormatDTOList);
            productDto.setItems(result.getObject("attr", ArrayList.class));
        } else {
            this.productFormat(productDto, result);
        }

        map.put("productInfo", productDto);

        return map;

    }

    /**
     * 商品上架下架
     *
     * @param id     商品id
     * @param status ShopCommonEnum
     */
    @Override
    public void onSale(Long id, Integer status) {
        if (ShopCommonEnum.SHOW.getValue().equals(status)) {
            status = ShopCommonEnum.NO_SHOW.getValue();
        } else {
            status = ShopCommonEnum.SHOW.getValue();
        }
        storeProductMapper.updateOnsale(status, id);
    }

    @Override
    public PageResult<StoreProductRespVO> getCanvasProductPage(CanvasProductPageReqVO pageReqVO) {
        if (pageReqVO.getCateId() != null) {
            ProductCategoryDO productCategoryDO = productCategoryService.getCategory(pageReqVO.getCateId());
            if (productCategoryDO != null) {
                List<Long> CateIds = new ArrayList<>();
                if (Objects.equals(productCategoryDO.getParentId(), ProductCategoryDO.PARENT_ID_NULL)) {
                    CateIds = productCategoryService.list((Wrappers.<ProductCategoryDO>lambdaQuery()
                                    .eq(ProductCategoryDO::getParentId, productCategoryDO.getId())))
                            .stream().map(ProductCategoryDO::getId).collect(Collectors.toList());
                } else {
                    CateIds.add(Convert.toLong(pageReqVO.getCateId()));
                }
                pageReqVO.setCateIds(CateIds);
            }
        }
        if (PageTypeEnum.NOT_PAGE.getValue().equals(pageReqVO.getIsPage())) pageReqVO.setPageSize(Integer.MAX_VALUE);
        PageResult<StoreProductRespVO> pageResult =
                StoreProductConvert.INSTANCE.convertPage(storeProductMapper.getCanvasProductPage(pageReqVO));
        List<StoreProductRespVO> list = pageResult.getList();
        if (CollectionUtils.isEmpty(list)) return pageResult;
        //  查询活动信息
        List<Long> productIds =
                pageResult.getList().stream().map(StoreProductRespVO::getId).collect(Collectors.toList());
        List<AppCampaignSkuRespVO> campaignDetailDOS = campaignDetailMapper.getCampaignSkus(productIds);
        Map<Long, List<AppCampaignSkuRespVO>> campaignDetailMap =
                campaignDetailDOS.stream().collect(Collectors.groupingBy(AppCampaignSkuRespVO::getProductId));
        for (StoreProductRespVO respVo : list) {
            Long productTagId = respVo.getProductTagId();
            if (productTagId != null) {
                respVo.setTag(productTagService.findTagById(productTagId));
            }
            List<AppCampaignSkuRespVO> detailDOS = campaignDetailMap.get(respVo.getId());
            if (CollectionUtils.isEmpty(detailDOS)) continue;
            // 默认显示第一个
            AppCampaignSkuRespVO skuRespVO = detailDOS.get(0);
            respVo.setSkuId(skuRespVO.getSkuId());
            respVo.setProductAttrUnique(skuRespVO.getProductAttrUnique());
            respVo.setCampaignType(skuRespVO.getType());
            respVo.setCampaignState(skuRespVO.getState());
            respVo.setCampaignOriginalPrice(skuRespVO.getCampaignOriginalPrice());
            respVo.setCampaignPrice(skuRespVO.getPrice());
            respVo.setCampaignStock(skuRespVO.getStock());
            respVo.setCampaignTotal(skuRespVO.getTotal());
            respVo.setPerson(skuRespVO.getPerson());
        }

        return pageResult;
    }

    @Override
    public PageResult<StoreProductDO> getProductPage(ProductPageReqVO pageReqVO) {
        return storeProductMapper.getProductPage(pageReqVO);
    }


    /**
     * 获取商品属性
     *
     * @param productDto 商品对象
     * @param result     属性result对象
     */
    private void productFormat(ProductDTO productDto, JSONObject result) {
        Map<String, Object> mapAttr = (Map<String, Object>) result.getObject("value", ArrayList.class).get(0);
        ProductFormatDTO productFormatDto = ProductFormatDTO.builder()
                .pic(mapAttr.get("pic").toString())
                .price(Double.valueOf(mapAttr.get("price").toString()))
                .cost(Double.valueOf(mapAttr.get("cost").toString()))
                .otPrice(Double.valueOf(mapAttr.get("otPrice").toString()))
                .stock(Integer.valueOf(mapAttr.get("stock").toString()))
                .barCode(mapAttr.get("barCode").toString())
                .weight(Double.valueOf(mapAttr.get("weight").toString()))
                .volume(Double.valueOf(mapAttr.get("volume").toString()))
                .value1(mapAttr.get("value1").toString())
                .integral(mapAttr.get("integral") != null ? Integer.parseInt(mapAttr.get("integral").toString()) : 0)
                .brokerage(Double.valueOf(mapAttr.get("brokerage").toString()))
                .brokerageTwo(Double.valueOf(mapAttr.get("brokerageTwo").toString()))
                .pinkPrice(Double.valueOf(mapAttr.get("pinkPrice").toString()))
                .pinkStock(Integer.valueOf(mapAttr.get("pinkStock").toString()))
                .seckillPrice(Double.valueOf(mapAttr.get("seckillPrice").toString()))
                .seckillStock(Integer.valueOf(mapAttr.get("seckillStock").toString()))
                .secondWages(ObjectUtil.isNotEmpty(mapAttr.get("secondWages")) ?
                        Integer.valueOf(mapAttr.get("secondWages").toString()) : null)
                .firstWages(ObjectUtil.isNotEmpty(mapAttr.get("firstWages")) ?
                        Integer.valueOf(mapAttr.get("firstWages").toString()) : null)
                .build();
        productDto.setAttr(productFormatDto);
    }


    /**
     * 计算产品数据
     *
     * @param attrs attrs
     * @return ProductResultDto
     */
    private ProductResultDTO computedProduct(List<ProductFormatDTO> attrs) {
        //取最小价格
        Double minPrice = attrs
                .stream()
                .map(ProductFormatDTO::getPrice)
                .min(Comparator.naturalOrder())
                .orElse(0d);

        //取最小积分
        Integer minIntegral = attrs
                .stream()
                .map(ProductFormatDTO::getIntegral)
                .min(Comparator.naturalOrder())
                .orElse(0);

        Double minOtPrice = attrs
                .stream()
                .map(ProductFormatDTO::getOtPrice)
                .min(Comparator.naturalOrder())
                .orElse(0d);

        Double minCost = attrs
                .stream()
                .map(ProductFormatDTO::getCost)
                .min(Comparator.naturalOrder())
                .orElse(0d);
        //计算库存
        Integer stock = attrs
                .stream()
                .map(ProductFormatDTO::getStock)
                .reduce(Integer::sum)
                .orElse(0);

        if (stock <= 0) {
            throw exception(STORE_PRODUCT_STOCK_ERROR);
        }

        return ProductResultDTO.builder()
                .minPrice(minPrice)
                .minOtPrice(minOtPrice)
                .minCost(minCost)
                .stock(stock)
                .minIntegral(minIntegral)
                .build();
    }


}
